package com.xinxing.learning.datasource.aop;

import com.xinxing.learning.datasource.annotation.DataSourceRouting;
import com.xinxing.learning.datasource.constants.DataSourceConstants;
import com.xinxing.learning.datasource.context.DynamicDataSourceContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.Objects;

@Aspect
@Component
public class DynamicDataSourceAspect {

    @Pointcut("@annotation(com.xinxing.learning.datasource.annotation.DataSourceRouting)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        DataSourceRouting annotation = getDSAnnotation(joinPoint);
        String dsKey = DataSourceConstants.DS_KEY_MASTER;
        if (Objects.nonNull(annotation)) {
            dsKey = annotation.value();
        }
        DynamicDataSourceContextHolder.setContextKey(dsKey);
        try {
            return joinPoint.proceed();
        } finally {
            DynamicDataSourceContextHolder.removeContextKey();
        }
    }

    public DataSourceRouting getDSAnnotation(ProceedingJoinPoint joinPoint) {
        Class<?> targetClass = joinPoint.getTarget().getClass();
        DataSourceRouting annotation = targetClass.getAnnotation(DataSourceRouting.class);
        if (Objects.nonNull(annotation)) {
            return annotation;
        } else {
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            annotation = methodSignature.getMethod().getAnnotation(DataSourceRouting.class);
            return annotation;
        }
    }
}
